home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_313 / uucp / uucp1.lzh / src / getty / getty.c < prev    next >
C/C++ Source or Header  |  1990-01-08  |  20KB  |  986 lines

  1.  
  2. /*
  3.  *  GETTY.C
  4.  *
  5.  *  (c)Copyright 1989, Matthew Dillon, All Rights Reserved
  6.  *
  7.  *  Uses:
  8.  *    GETTY:PASSWD
  9.  *    GETTY:LOGFILE
  10.  *    GETTY:Getty-Header
  11.  *
  12.  *  GETTY   <options>    <modem-commands>
  13.  *
  14.  *    -Sdevicenam Tells GETTY which serial.device to use, default
  15.  *            serial.device
  16.  *
  17.  *    -Uunitnum   Tells GETTY which unit number to use, default 0
  18.  *
  19.  *    -A        Always talk to the modem at the first baud
  20.  *            rate in the -B list and ignore the baud rate
  21.  *            in the CONNECT message.
  22.  *
  23.  *    -7        use SERF_7WIRE while online.
  24.  *
  25.  *    -Bn        Set baud rate.  If specified multiple times the
  26.  *            first one is the default and remaining ones
  27.  *            switched to when a BREAK is received after a
  28.  *            connect.  Also determines how CONNECT messages
  29.  *            are interpreted.  A CONNECT with no number uses
  30.  *            the first -B entry while CONNECTs with numbers
  31.  *            use those numbers regardless of any -B entries.
  32.  *
  33.  *    -Mc        Set modem type:
  34.  *            c = m    = multimodem
  35.  *                h    = hays
  36.  *                d    = dumb (no AT or +++ cmds are ever sent),
  37.  *                  normally used with only one specified
  38.  *                  baud rate.
  39.  *
  40.  *    -m1        Turn on the modem speaker during dialing/connect
  41.  *            (default is -m0)
  42.  *
  43.  *    -h0        Ignore CD (carrier detect), default is to use
  44.  *            carrier detect.
  45.  *
  46.  *    -c0        Ignore CONNECT message (i.e. you are not connected
  47.  *            to a modem, usually combined with -h0).  Default is
  48.  *            to expect a CONNECT message.
  49.  *
  50.  *    -d0        do not use DTR to drop connection.    Default is
  51.  *            to drop DTR to drop a connection.  If this option
  52.  *            is chosen the +++ and ATH0 sequence will be used
  53.  *            to drop a connection.
  54.  *
  55.  *    -xn        Set debug level.  Also causes log output to go
  56.  *            to stdout instead of GETTY:LOGFILE
  57.  *
  58.  *    -0        QUIT - Kills any running getty for the specified
  59.  *            port.
  60.  *
  61.  *    Any fields specified without a '-' are considered modem commands
  62.  *    used to initialize/reinitialize the modem.  Up to 16 fields may
  63.  *    be specified (each is sent to the modem in 1 second intervals)
  64.  */
  65.  
  66. #include <exec/types.h>
  67. #include <exec/lists.h>
  68. #include <exec/devices.h>
  69. #include <devices/timer.h>
  70. #include <devices/serial.h>
  71. #include <libraries/dos.h>
  72. #include <libraries/dosextens.h>
  73. #include <hardware/cia.h>
  74. #include <stdio.h>
  75. #include <stdlib.h>
  76. #include <proto/all.h>
  77. #include <pwd.h>
  78. #include "/version.h"
  79.  
  80. #include "log.h"
  81.  
  82. IDENT(".01");
  83.  
  84. #define arysize(ary)    (sizeof(ary)/sizeof((ary)[0]))
  85.  
  86. #define ST_WAITCD    0
  87. #define ST_CONNECT    1
  88. #define ST_LOGIN    2
  89. #define ST_PASSWD    3
  90. #define ST_RUN        4
  91.  
  92. typedef struct IORequest    IOR;
  93. typedef struct timerequest  IOT;
  94. typedef struct IOExtSer     IOSER;
  95. typedef struct MsgPort        PORT;
  96. typedef struct List        LIST;
  97. typedef struct Node        NODE;
  98. typedef struct Message        MSG;
  99.  
  100. typedef struct GMsg {
  101.     struct Message  Msg;
  102.     short   Cmd;
  103.     long    Data1;
  104.     void    *Data2;
  105. } GMsg;
  106.  
  107. extern struct ProcID *RunPasswdEntry();
  108.  
  109. char    *CopyRight = "(c)Copyright 1989, Matthew Dillon, All Rights Reserved\r\n";
  110. char    *ComPortName;
  111.  
  112. char    *DeviceName = "serial.device";
  113. long    DeviceUnit  = 0;
  114. long    NullFH;
  115. char    SpeakerLevel    = 0;
  116. char    AnswerRing    = 2;    /*  default, answer on second ring */
  117. char    SpeakerOpt    = 0;
  118. char    IgnoreCD    = 0;
  119. char    IgnoreConnect    = 0;
  120. char    IgnoreDTR    = 0;
  121. char    BaudAdjust    = 0;
  122. char    DropOnExit    = 1;
  123. char    ModemType    = 'h';
  124. char    ZeroOption    = 0;
  125. char    Wire7        = 0;        /*  use 7 wire while online */
  126. char    Locked        = 0;        /*  serial port is lcked    */
  127. long    Bauds[16] = { 9600 };        /*  up 16 baud rates        */
  128. char    *AtFields[16];
  129.  
  130. PORT    *ComPort;
  131. PORT    *IoSink;    /*  Sink for IO reqs.    */
  132. long    IoSinkMask;
  133. long    ComPortMask;
  134.  
  135. IOT    Iot;        /*  check-carrier    */
  136. IOSER    Iosr;        /*  serial read-req    */
  137. IOSER    Iosw;        /*  serial write-req    */
  138.  
  139. char    IotIP;        /*  Iot0 in progress    */
  140. char    IosrIP;
  141.  
  142. char    ScrBuf[256];
  143. char    ConnectBuf[64];
  144. char    LoginBuf[32];
  145. char    PasswdBuf[32];
  146. char    RxBuf[32];
  147. char    HaveConnectMsg;
  148. char    HaveLogin;
  149. char    HavePasswd;
  150.  
  151. short    State;
  152. short    Index;
  153. short    BIndex;
  154.  
  155. short CountDown;
  156. short GotOffPort;
  157.  
  158. void    SerPuts();
  159. void    Set7Wire();
  160. void    xexit();
  161. void    Disconnect();
  162. void    ClearRecv();
  163. void    InitModem();
  164. void    SetParams();
  165. void    DoOptions();
  166. void    SerialOff();
  167.  
  168. CXBRK()
  169. {
  170.     return(0);
  171. }
  172.  
  173. main(ac, av)
  174. char *av[];
  175. {
  176.     extern int IAmGetty;
  177.  
  178.     IAmGetty = 1;    /*  for LockSerialPort()/UnLockSerialPort()   */
  179.  
  180.     puts(CopyRight);
  181.     fflush(stdout);
  182.  
  183.     LogProgram = "Getty";
  184.     LogWho = LoginBuf;
  185.     LogFile = "Getty:LOGFILE";
  186.     PasswdFile = "Getty:Passwd";
  187.  
  188.     DoOptions(ac, av);
  189.  
  190.     IoSink = CreatePort(NULL, 0);
  191.     IoSinkMask = 1 << IoSink->mp_SigBit;
  192.  
  193.     ComPortName = malloc(strlen(DeviceName) + 20);
  194.     sprintf(ComPortName, "Getty.%s.%d", DeviceName, DeviceUnit);
  195.  
  196.     Forbid();
  197.     if (ComPort = FindPort(ComPortName)) {
  198.     GMsg msg;
  199.     msg.Cmd = 'O';
  200.     msg.Data1 = ac;
  201.     msg.Data2 = (void *)av;
  202.     msg.Msg.mn_ReplyPort = IoSink;
  203.     PutMsg(ComPort, &msg.Msg);
  204.     WaitPort(IoSink);
  205.     Remove(&msg);
  206.     Permit();
  207.     puts("Options updated");
  208.     xexit(0);
  209.     }
  210.     ComPort = CreatePort(ComPortName, 0);
  211.     Permit();
  212.  
  213.     ComPortMask = 1 << ComPort->mp_SigBit;
  214.  
  215.     NullFH = Open("NULL:", 1006);
  216.     if (NullFH == NULL) {
  217.     ulog(-1, "GETTY REQUIRES NULL: HANDLER!");
  218.     puts("Requires NULL: handler!");
  219.     xexit(1);
  220.     }
  221.     if (LogToStdout == 0) {
  222.     freopen("NULL:", "r", stdin);
  223.     freopen("NULL:", "w", stdout);
  224.     freopen("NULL:", "w", stderr);
  225.     }
  226.  
  227.  
  228.     /*
  229.      *    Timer Device
  230.      */
  231.  
  232.     Iot.tr_node.io_Message.mn_ReplyPort = IoSink;
  233.     if (OpenDevice("timer.device", UNIT_VBLANK, &Iot, 0)) {
  234.     Iot.tr_node.io_Device = NULL;
  235.     xexit(20);
  236.     }
  237.     Iot.tr_node.io_Command = TR_ADDREQUEST;
  238.  
  239.     /*
  240.      *    SERIAL.DEVICE
  241.      */
  242.  
  243.     Iosr.IOSer.io_Message.mn_ReplyPort = IoSink;
  244.     Iosr.io_SerFlags = SERF_XDISABLED | SERF_7WIRE | SERF_RAD_BOOGIE | SERF_SHARED;
  245.     if (OpenDevice(DeviceName, DeviceUnit, &Iosr, 0)) {
  246.     Iosr.IOSer.io_Device = NULL;
  247.     xexit(21);
  248.     }
  249.  
  250.     Iosw = Iosr;
  251.  
  252.     Iosw.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE | SERF_SHARED;
  253.     Iosw.io_ExtFlags = 0;
  254.     Iosw.io_Baud = Bauds[0];
  255.     Iosw.io_ReadLen = 8;
  256.     Iosw.io_WriteLen = 8;
  257.     Iosw.io_StopBits = 1;
  258.  
  259.     SetParams(&Iosw);
  260.  
  261.     /*
  262.      *    Run Operation
  263.      */
  264.  
  265.     State = ST_WAITCD;
  266.     Iot.tr_time.tv_secs = 1;
  267.     Iot.tr_time.tv_micro= 0;
  268.     IotIP = 1;
  269.     SendIO(&Iot);
  270.  
  271.     InitModem();
  272.  
  273.     Signal(FindTask(NULL), IoSinkMask);
  274.  
  275.     for (;;) {
  276.     long mask;
  277.     IOR  *ior;
  278.     GMsg *msg;
  279.     mask = Wait(SIGBREAKF_CTRL_C | IoSinkMask | ComPortMask);
  280.  
  281.     ulog(2, "State = %d", State);
  282.  
  283.     if (mask & SIGBREAKF_CTRL_C)
  284.         break;
  285.  
  286.     if (msg = (GMsg *)GetMsg(ComPort)) {
  287.         do {
  288.         switch(msg->Cmd) {
  289.         case 'O':
  290.             DoOptions(msg->Data1, msg->Data2);
  291.             break;
  292.         }
  293.         ReplyMsg((MSG *)msg);
  294.         if (ZeroOption)
  295.             xexit(0);
  296.         } while (msg = (GMsg *)GetMsg(ComPort));
  297.         if (State == ST_WAITCD && !GotOffPort)
  298.         Disconnect(0);
  299.     }
  300.  
  301.     while (ior = (IOR *)GetMsg(IoSink)) {
  302.         if (ior == (IOR *)&Iot) {
  303.         short diu;
  304.  
  305.         IotIP = 0;
  306.         Iot.tr_time.tv_secs = 1;
  307.         Iot.tr_time.tv_micro= 0;
  308.  
  309.         /*
  310.          *  If OpenCnt > 1, disable all processing.
  311.          *
  312.          *  When returns to <= 1 reset serial port.
  313.          */
  314.  
  315.         diu = DeviceInUse();
  316.         if (diu) {
  317.             if (GotOffPort == 0) {
  318.             ulog(-1, "Device in use");
  319.             if (Locked)
  320.                 ulog(-1, "getting off port");
  321.             SerialOff();
  322.             GotOffPort = 1;
  323.             State = ST_WAITCD;
  324.             }
  325.             SendIO(&Iot);
  326.             IotIP = 1;
  327.             continue;
  328.         }
  329.         if (GotOffPort) {
  330.             if (Locked == 0) {
  331.             LockSerialPort(DeviceName, DeviceUnit);
  332.             Locked = 1;
  333.             }
  334.             GotOffPort = 0;
  335.             ulog(-1, "Getty resetting");
  336.             SendIO(&Iot);
  337.             IotIP = 1;
  338.             Disconnect(1);
  339.             continue;
  340.         }
  341.         if (State == ST_WAITCD)
  342.             SerialOff();
  343.  
  344.         if (State != ST_WAITCD && IosrIP == 0) {
  345.             if (Locked == 0)
  346.             LockSerialPort(DeviceName, DeviceUnit);
  347.             Locked = 1;
  348.             ulog(-1, "Serial Port Locked");
  349.  
  350.             Iosr.IOSer.io_Command = CMD_READ;
  351.             Iosr.IOSer.io_Data = (APTR)RxBuf;
  352.             Iosr.IOSer.io_Length = 1;
  353.             SendIO(&Iosr);
  354.             IosrIP = 1;
  355.             ulog(1, "Carrier, Getty getting on port");
  356.         }
  357.  
  358.         Iosw.IOSer.io_Command = SDCMD_QUERY;
  359.         DoIO(&Iosw);
  360.         if (IgnoreCD)
  361.             Iosw.io_Status &= ~CIAF_COMCD;
  362.  
  363.         /*
  364.          *  If state connected and we loose carrier, disconnect.
  365.          *
  366.          *  If state connected and timeout occurs disconnect.
  367.          */
  368.  
  369.         if (State != ST_WAITCD) {
  370.             if ((Iosw.io_Status & CIAF_COMCD) != 0) {
  371.             ulog(1, "Getty, Carrier lost");
  372.             Disconnect(0);
  373.             } else {
  374.             if (--CountDown == 0) {
  375.                 ulog(1, "Getty, Timeout, Disconnecting");
  376.                 Disconnect(1);
  377.                 Iosw.io_Status |= CIAF_COMCD; /* for below */
  378.             }
  379.             }
  380.         }
  381.  
  382.         switch(State) {
  383.         case ST_WAITCD:
  384.             if ((Iosw.io_Status & CIAF_COMCD) == 0) {
  385.             State = ST_CONNECT;
  386.             CountDown = 60;     /*    allow 60 seconds */
  387.             ulog(-1, "Carrier Detect");
  388.             } else {
  389.             Iot.tr_time.tv_secs = 2;
  390.             }
  391.             break;
  392.         case ST_CONNECT:
  393.             /*
  394.              *    Wait for CONNECT message, then send Login:
  395.              */
  396.  
  397.             if (IgnoreConnect && HaveConnectMsg == 0) {
  398.             if (Wire7)
  399.                 Set7Wire(&Iosw);
  400.             HaveConnectMsg = 1;
  401.             ulog(-1, "Connect");
  402.             }
  403.  
  404.             if (HaveConnectMsg) {
  405.             FILE *fi;
  406.  
  407.             Delay(50);
  408.             ClearRecv();
  409.             if (fi = fopen("Getty:Getty-Header", "r")) {
  410.                 while (fgets(ScrBuf, sizeof(ScrBuf), fi)) {
  411.                 SerPuts(ScrBuf);
  412.                 SerPuts("\r");
  413.                 }
  414.                 fclose(fi);
  415.             }
  416.             SerPuts("Login: ");
  417.             ulog(-1, "Getty, Connect, Login");
  418.             State = ST_LOGIN;
  419.             Index = 0;
  420.             HaveLogin = 0;
  421.             LoginBuf[0] = 0;
  422.             }
  423.             break;
  424.         case ST_LOGIN:        /*    wait Login: response    */
  425.             if (HaveLogin) {
  426.             if (LoginBuf[0] == 0) {
  427.                 State = ST_CONNECT;
  428.                 break;
  429.             }
  430.             ClearRecv();
  431.             PasswdBuf[0] = 0;
  432.  
  433.             /*
  434.              *  If no password required, else request
  435.              *  password.
  436.              */
  437.  
  438.             if (CheckLoginAndPassword()) {
  439.                 HavePasswd = 1;
  440.                 Index = 0;
  441.                 State = ST_PASSWD;
  442.             } else {
  443.                 SerPuts("Password: ");
  444.                 ulog(1, "Getty, Passwd");
  445.                 State = ST_PASSWD;
  446.                 HavePasswd = 0;
  447.                 Index = 0;
  448.             }
  449.             }
  450.             break;
  451.         case ST_PASSWD:     /*    wait Password: response */
  452.             if (HavePasswd) {
  453.             if (CheckLoginAndPassword()) {
  454.                 ulog(-1, "login %s", LoginBuf);
  455.  
  456.                 /*
  457.                  *    Disable read requests but leave serial
  458.                  *    port locked.
  459.                  */
  460.  
  461.                 if (IosrIP) {
  462.                 AbortIO(&Iosr);
  463.                 WaitIO(&Iosr);
  464.                 IosrIP = 0;
  465.                 }
  466.  
  467.                 /*
  468.                  *    If run successful, leave read req and
  469.                  *    timer disabled.
  470.                  */
  471.  
  472.                 RunPasswdEntry();
  473.  
  474.                 if (DropOnExit)
  475.                 Disconnect(1);
  476.                 else
  477.                 State = ST_CONNECT;
  478.                 ulog(-1, "disconnect");
  479.             } else {
  480.                 SerPuts("Login Failed.\r\n\n");
  481.                 State = ST_CONNECT;
  482.                 ulog(-1, "LoginFailed user=%s pass=%s", LoginBuf, PasswdBuf);
  483.             }
  484.             HaveLogin = 0;
  485.             HavePasswd= 0;
  486.             LoginBuf[0] = 0;
  487.             }
  488.             break;
  489.         }
  490.  
  491.         /*
  492.          *  Make no read requests while running 3rd party
  493.          *  program, else resend read request.
  494.          */
  495.  
  496.         if (IotIP == 0) {
  497.             IotIP = 1;
  498.             SendIO(&Iot);
  499.         }
  500.         }
  501.  
  502.         /*
  503.          *    RECEIVED SERIAL READ DATA
  504.          */
  505.  
  506.         if (ior == (IOR *)&Iosr) {
  507.         IosrIP = 0;
  508.  
  509.         Iosw.IOSer.io_Command = SDCMD_QUERY;
  510.         DoIO(&Iosw);
  511.         if (IgnoreCD)
  512.             Iosw.io_Status &= ~CIAF_COMCD;
  513.  
  514.         /*
  515.          *  BREAK used to switch baud rates between allowed
  516.          *  values
  517.          */
  518.  
  519.         if (Iosw.io_Status & IO_STATF_READBREAK) {
  520.             if (BaudAdjust == 0 && (State == ST_LOGIN || State == ST_PASSWD)) {
  521.             if (++BIndex == arysize(Bauds))
  522.                 BIndex = 0;
  523.             if (Bauds[BIndex] == 0)
  524.                 BIndex = 0;
  525.             Iosw.io_Baud = Bauds[BIndex];
  526.             SetParams(&Iosw);
  527.             if (Wire7)
  528.                 Set7Wire(&Iosw);
  529.             ulog(1, "<BREAK> to %d baud", Iosw.io_Baud);
  530.             Delay(100);
  531.             ClearRecv();
  532.             Index = 0;
  533.             State = ST_CONNECT;
  534.             }
  535.         } else
  536.         if (Iosr.IOSer.io_Actual == 1) {
  537.             char *ptr;
  538.             UBYTE c = (UBYTE)RxBuf[0];
  539.  
  540.             ulog(2, "Rx %02x %c", c, (c < 32) ? ' ' : c);
  541.             c &= 0x7F;
  542.  
  543.             switch(State) {
  544.             case ST_WAITCD:    /*  looking for CONNECT msg */
  545.             case ST_CONNECT:    /*  looking for CONNECT msg */
  546.             ptr = ConnectBuf;
  547.             break;
  548.             case ST_LOGIN:    /*  looking for login name  */
  549.             ptr = LoginBuf;
  550.             break;
  551.             case ST_PASSWD:    /*  looking for password    */
  552.             ptr = PasswdBuf;
  553.             break;
  554.             }
  555.             if (State == ST_LOGIN && HaveLogin)
  556.             c = 0;
  557.             if (State == ST_PASSWD && HavePasswd)
  558.             c = 0;
  559.  
  560.             switch(c) {
  561.             case 0:
  562.             break;
  563.             case 8:
  564.             if (State == ST_LOGIN && HaveLogin)
  565.                 break;
  566.             if (Index) {
  567.                 if (State == ST_LOGIN)
  568.                 SerPuts("\010 \010");
  569.                 --Index;
  570.             }
  571.             break;
  572.             case 10:
  573.             case 13:
  574.             ptr[Index] = 0;
  575.             Index = 0;
  576.             switch(State) {
  577.             case ST_WAITCD:
  578.             case ST_CONNECT:
  579.                 if (strncmp(ptr, "CONNECT", 7)) {
  580.                 ulog(1, "Looking for CONNECT, got '%s'", ptr);
  581.                 break;
  582.                 }
  583.                 Delay(50);
  584.                 HaveConnectMsg = 1;
  585.                 if (BaudAdjust) {
  586.                 ulog(-1, "Connect Auto-Baud %d", Iosw.io_Baud);
  587.                 } else {
  588.                 char *str = ptr + 7;
  589.                 while (*str && (*str == 9 || *str == ' '))
  590.                     ++str;
  591.                 if (*str >= '0' && *str <= '9')
  592.                     Iosw.io_Baud = atoi(str);
  593.                 else
  594.                     Iosw.io_Baud = Bauds[0];
  595.                 SetParams(&Iosw);
  596.                 ulog(-1, "Connect at %d baud", Iosw.io_Baud);
  597.                 }
  598.                 if (Wire7)
  599.                 Set7Wire(&Iosw);
  600.                 break;
  601.             case ST_LOGIN:
  602.                 HaveLogin = 1;
  603.                 SerPuts("\r\n");
  604.                 ulog(1, "Login: %s", ptr);
  605.                 break;
  606.             case ST_PASSWD:
  607.                 HavePasswd = 1;
  608.                 SerPuts("\r\n");
  609.                 ulog(1, "Password: %s", ptr);
  610.                 break;
  611.             }
  612.             break;
  613.             default:
  614.             if (Index == 31)
  615.                 break;
  616.             if (State == ST_LOGIN) {
  617.                 char cc[2];
  618.                 cc[0] = c;
  619.                 cc[1] = 0;
  620.                 SerPuts(cc);
  621.             }
  622.             ptr[Index++] = c;
  623.             break;
  624.             }
  625.         }
  626.         if (IosrIP == 0) {
  627.             Iosr.IOSer.io_Command = CMD_READ;
  628.             Iosr.IOSer.io_Data = (APTR)RxBuf;
  629.             Iosr.IOSer.io_Length = 1;
  630.             SendIO(&Iosr);
  631.             IosrIP = 1;
  632.         }
  633.         }
  634.     }
  635.     }
  636.     xexit(0);
  637. }
  638.  
  639. void
  640. SerialOff()
  641. {
  642.     if (IosrIP) {
  643.     AbortIO(&Iosr);
  644.     WaitIO(&Iosr);
  645.     IosrIP = 0;
  646.     }
  647.     if (Locked) {
  648.     UnLockSerialPort(DeviceName, DeviceUnit);
  649.     Locked = 0;
  650.     ulog(1, "Serial Port UnLocked");
  651.     }
  652. }
  653.  
  654. void
  655. xexit(code)
  656. {
  657.     if (ComPortMask) {
  658.     GMsg *msg;
  659.     Forbid();
  660.     while (msg = (GMsg *)GetMsg(ComPort))
  661.         ReplyMsg((MSG *)msg);
  662.     DeletePort(ComPort);
  663.     Permit();
  664.     }
  665.     if (IotIP) {
  666.     AbortIO(&Iot);
  667.     WaitIO(&Iot);
  668.     }
  669.     if (Iot.tr_node.io_Device)
  670.     CloseDevice(&Iot);
  671.  
  672.     if (IosrIP) {
  673.     AbortIO(&Iosr);
  674.     WaitIO(&Iosr);
  675.     }
  676.     if (Iosr.IOSer.io_Device)
  677.     CloseDevice(&Iosr);
  678.  
  679.     if (IoSink)
  680.     DeletePort(IoSink);
  681.  
  682.     if (NullFH)
  683.     Close(NullFH);
  684.  
  685.     if (Locked)
  686.     UnLockSerialPort(DeviceName, DeviceUnit);
  687.  
  688.     exit(code);
  689. }
  690.  
  691. void
  692. SerPuts(str)
  693. char *str;
  694. {
  695.     Iosw.IOSer.io_Command = CMD_WRITE;
  696.     Iosw.IOSer.io_Data = (APTR)str;
  697.     Iosw.IOSer.io_Length = strlen(str);
  698.     DoIO(&Iosw);
  699. }
  700.  
  701. static short RxDisableIP;
  702.  
  703. void
  704. RxDisable()
  705. {
  706.     RxDisableIP = IosrIP;
  707.     if (IosrIP) {
  708.     AbortIO(&Iosr);
  709.     WaitIO(&Iosr);
  710.     IosrIP = 0;
  711.     }
  712. }
  713.  
  714. void
  715. RxEnable()
  716. {
  717.     if (RxDisableIP && IosrIP == 0) {
  718.     Iosr.IOSer.io_Command = CMD_READ;
  719.     Iosr.IOSer.io_Data = (APTR)RxBuf;
  720.     Iosr.IOSer.io_Length = 1;
  721.     SendIO(&Iosr);
  722.     IosrIP = 1;
  723.     }
  724. }
  725.  
  726. void
  727. ClearRecv()
  728. {
  729.     RxDisable();
  730.     ulog(1, "Clear beg");
  731.     for (;;) {
  732.     Iosr.IOSer.io_Command = SDCMD_QUERY;
  733.     DoIO(&Iosr);
  734.     if ((Iosr.IOSer.io_Length = Iosr.IOSer.io_Actual) <= 0)
  735.         break;
  736.     if (Iosr.IOSer.io_Length > sizeof(RxBuf))
  737.         Iosr.IOSer.io_Length = sizeof(RxBuf);
  738.     Iosr.IOSer.io_Data = (APTR)RxBuf;
  739.     Iosr.IOSer.io_Command = CMD_READ;
  740.     DoIO(&Iosr);
  741.     }
  742.     ulog(1, "Clear end");
  743.     RxEnable();
  744. }
  745.  
  746. void
  747. SetParams(ior)
  748. IOSER *ior;
  749. {
  750.     int error;
  751.  
  752.     if (IosrIP)
  753.     AbortIO(&Iosr);
  754.     ior->IOSer.io_Command = SDCMD_SETPARAMS;
  755.     error = DoIO(ior);
  756.     if (error)
  757.     printf("SetParams, error %d\n", error);
  758. }
  759.  
  760. void
  761. Set7Wire(ior)
  762. IOSER *ior;
  763. {
  764.     short error;
  765.  
  766.     if (IosrIP)
  767.     AbortIO(&Iosr);
  768.     ior->IOSer.io_Command = SDCMD_SETPARAMS;
  769.     ior->io_SerFlags |= SERF_7WIRE;
  770.     error = DoIO(ior);
  771.     ior->io_SerFlags &= ~SERF_7WIRE;
  772.     if (error)
  773.     printf("SetParams, error %d\n", error);
  774. }
  775.  
  776. void
  777. Disconnect(dropdtr)
  778. {
  779.     short retry = (IgnoreDTR) ? 2 : 10;
  780.  
  781.     ulog(1, "Disconnect drop=%d", dropdtr);
  782.     HaveConnectMsg = 0;
  783.     HaveLogin    = 0;
  784.     HavePasswd    = 0;
  785.     LoginBuf[0] = 0;
  786.     PasswdBuf[0] = 0;
  787.     Index = 0;
  788.     State = ST_WAITCD;
  789.  
  790.     while (dropdtr && DeviceInUse() == 0) {
  791.     short i;
  792.  
  793.     RxDisable();
  794.  
  795.     if (IgnoreDTR) {
  796.         if (ModemType != 'd') {
  797.         Delay(70);
  798.         SerPuts("+++");
  799.         Delay(70);
  800.         SerPuts("\010\010\r");
  801.         Delay(10);
  802.         SerPuts("ATH0\r");
  803.         Delay(120);
  804.         }
  805.     } else {
  806.         CloseDevice(&Iosr);
  807.         Iosr.IOSer.io_Device = NULL;    /*    so xexit doesn't reclose */
  808.         for (i = 0; i < 5; ++i) {       /*  5 seconds   */
  809.         Delay(50);
  810.         if (SetSignal(SIGBREAKF_CTRL_C, 0) & SIGBREAKF_CTRL_C)
  811.             xexit(23);
  812.         }
  813.  
  814.        /*
  815.         *  Use Iosr to re-open serial device so we don't loose
  816.         *  our config.
  817.         */
  818.  
  819.         if (OpenDevice(DeviceName, DeviceUnit, &Iosr, 0)) {
  820.         Iosr.IOSer.io_Device = NULL;
  821.         xexit(22);
  822.         }
  823.         Iosw.IOSer.io_Device = Iosr.IOSer.io_Device;
  824.         Iosw.IOSer.io_Unit = Iosr.IOSer.io_Unit;
  825.         SetParams(&Iosw);
  826.     }
  827.  
  828.     /*
  829.      *  Loop until carrier lost
  830.      */
  831.  
  832.     Iosw.IOSer.io_Command = SDCMD_QUERY;
  833.     DoIO(&Iosw);
  834.     if (IgnoreCD)
  835.         Iosw.io_Status &= ~CIAF_COMCD;
  836.  
  837.     RxEnable();
  838.  
  839.     if ((Iosw.io_Status & CIAF_COMCD) != 0)
  840.         break;
  841.     if (--retry == 0) {
  842.         if (IgnoreDTR == 0)
  843.         puts("Getty: unable to disconnect!");
  844.         break;
  845.     }
  846.     }
  847.     if (DeviceInUse() == 0)
  848.     InitModem();
  849. }
  850.  
  851. void
  852. InitModem()
  853. {
  854.     char buf[64];
  855.     short i;
  856.  
  857.     RxDisable();
  858.     ulog(1, "Init Modem");
  859.     Iosw.io_Baud = Bauds[0];    /*  reset baud rate */
  860.     BIndex = 0;
  861.     SetParams(&Iosw);
  862.     RxEnable();
  863.  
  864.     switch(ModemType) {
  865.     case 'm':               /*  Multi Modem     */
  866.     SerPuts("\010\010\r");
  867.     Delay(10);
  868.     SerPuts("AT\r");
  869.     Delay(50);
  870.     sprintf(buf, "ATM%dS0=%dX4$BA%d&E%d\r",
  871.         SpeakerLevel,
  872.         AnswerRing,
  873.         !BaudAdjust,
  874.         (Wire7) ? 4 : 3
  875.     );
  876.     SerPuts(buf);
  877.     break;
  878.     case 'h':
  879.     SerPuts("\010\010\r");
  880.     Delay(10);
  881.     SerPuts("ATZ\r");
  882.     Delay(120);
  883.     strcpy(buf, "AT");
  884.     if (SpeakerOpt)
  885.         sprintf(buf + strlen(buf), "M%d", SpeakerLevel);
  886.     sprintf(buf + strlen(buf), "S0=%d", AnswerRing);
  887.     strcat(buf, "\r");
  888.     SerPuts(buf);
  889.     break;
  890.     case 'd':
  891.     SerPuts("\010\010\r");
  892.     break;
  893.     }
  894.     for (i = 0; i < arysize(AtFields) && AtFields[i]; ++i) {
  895.     Delay(50);
  896.     SerPuts(AtFields[i]);
  897.     SerPuts("\r");
  898.     }
  899.     Delay(20);
  900.     ClearRecv();
  901.     Index = 0;
  902. }
  903.  
  904. void
  905. DoOptions(ac, av)
  906. char *av[];
  907. {
  908.     short i;
  909.     short bi = 0;
  910.     short fi = 0;
  911.     long v;
  912.  
  913.     for (i = 1; i < ac; ++i) {
  914.     char *ptr = av[i];
  915.     if (*ptr != '-') {
  916.         if (fi != arysize(AtFields))
  917.         AtFields[fi++] = ptr;
  918.         else
  919.         puts("AT field overflow");
  920.         continue;
  921.     }
  922.     if (*++ptr)             /*  skip -      */
  923.         ++ptr;        /*  and option    */
  924.     v = atoi(ptr);
  925.     switch(ptr[-1]) {
  926.     case '0':
  927.         ZeroOption = 1;
  928.         break;
  929.     case '7':
  930.         Wire7 = 1;
  931.         break;
  932.     case 'S':
  933.         DeviceName = ptr;
  934.         break;
  935.     case 'U':
  936.         DeviceUnit = v;
  937.         break;
  938.     case 'M':
  939.         ModemType = *ptr;
  940.         break;
  941.     case 'A':
  942.         BaudAdjust = 1;
  943.         break;
  944.     case 'B':
  945.         if (bi != arysize(Bauds))
  946.         Bauds[bi++] = v;
  947.         else
  948.         puts("-B field overflow");
  949.         break;
  950.     case 'm':
  951.         SpeakerOpt = 1;
  952.         SpeakerLevel = v;
  953.         break;
  954.     case 'r':
  955.         AnswerRing = v;
  956.         break;
  957.     case 'h':
  958.         IgnoreCD = !v;
  959.         break;
  960.     case 'c':
  961.         IgnoreConnect = !v;
  962.         break;
  963.     case 'd':
  964.         IgnoreDTR = !v;
  965.         break;
  966.     case 'x':
  967.         LogLevel = v;
  968.         LogToStdout = (v >= 0);
  969.         break;
  970.     default:
  971.         printf("Warning, Bad option: -%s\n", ptr);
  972.         break;
  973.     }
  974.     }
  975.     if (fi && fi != arysize(AtFields))
  976.     AtFields[fi] = NULL;
  977.     if (bi && bi != arysize(Bauds))
  978.     Bauds[bi] = 0;
  979. }
  980.  
  981. DeviceInUse()
  982. {
  983.     return(Iosr.IOSer.io_Device->dd_Library.lib_OpenCnt > 1);
  984. }
  985.  
  986.